home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / Sources / FWRegion.cpp < prev    next >
Encoding:
Text File  |  1995-11-08  |  21.7 KB  |  766 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWRegion.cpp
  4. //    Release Version:    $ 1.0d11 $
  5. //
  6. //    Copyright:    © 1993, 1995 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef FWREGION_H
  13. #include "FWRegion.h"
  14. #endif
  15.  
  16. #ifndef FWFXMATH_H
  17. #include "FWFxMath.h"
  18. #endif
  19.  
  20. #ifndef FWGRUTIL_H
  21. #include "FWGrUtil.h"
  22. #endif
  23.  
  24. #ifndef FWGRGLOB_H
  25. #include "FWGrGlob.h"
  26. #endif
  27.  
  28. #ifndef FWGRDEF_H
  29. #include "FWGrDef.h"
  30. #endif
  31.  
  32. // ----- Foundation Includes -----
  33.  
  34. #ifndef FWSTREAM_H
  35. #include "FWStream.h"
  36. #endif
  37.  
  38. #ifndef FWDEBUG_H
  39. #include "FWDebug.h"
  40. #endif
  41.  
  42. #ifndef FWMEMHLP_H
  43. #include "FWMemHlp.h"
  44. #endif
  45.  
  46. //========================================================================================
  47. //    RunTime Info
  48. //========================================================================================
  49.  
  50. #if FW_LIB_EXPORT_PRAGMAS
  51. #pragma lib_export on
  52. #endif
  53.  
  54. #ifdef FW_BUILD_MAC
  55. #pragma segment FWGraphx_Region
  56. #endif
  57.  
  58. //========================================================================================
  59. //    Region utilities
  60. //========================================================================================
  61.  
  62. //----------------------------------------------------------------------------------------
  63. //    FW_NewRegion
  64. //----------------------------------------------------------------------------------------
  65.  
  66. FW_FUNC_ATTR ODRgnHandle FW_NewRegion()
  67. {    
  68. #ifdef FW_BUILD_MAC
  69.     return ::NewRgn();
  70. #endif
  71. #ifdef FW_BUILD_WIN
  72.     return    ::CreateRectRgn(0,0,0,0);
  73. #endif
  74. }
  75.  
  76. //----------------------------------------------------------------------------------------
  77. //    FW_CreateRectRegion
  78. //----------------------------------------------------------------------------------------
  79.  
  80. FW_FUNC_ATTR ODRgnHandle FW_CreateRectRegion(const FW_CRect& rect)
  81. {
  82.     FW_SPlatformRect plfmRect = rect;
  83.     
  84. #ifdef FW_BUILD_MAC
  85.     ODRgnHandle rgn = ::NewRgn();
  86.     ::RectRgn(rgn, &plfmRect);
  87.     return rgn;
  88. #endif
  89. #ifdef FW_BUILD_WIN
  90.     return ::CreateRectRgnIndirect(&plfmRect);
  91. #endif
  92. }
  93.  
  94. //----------------------------------------------------------------------------------------
  95. //    FW_CreateOvalRegion
  96. //----------------------------------------------------------------------------------------
  97.  
  98. FW_FUNC_ATTR ODRgnHandle FW_CreateOvalRegion(const FW_CRect& rect)
  99. {
  100.     FW_SPlatformRect plfmRect(rect);
  101.  
  102. #ifdef FW_BUILD_MAC
  103.     GrafPtr svPort = FW_PrivMacOpenRegion();
  104.     ::FrameOval(&plfmRect);
  105.     return FW_PrivMacCloseRegion(svPort);
  106. #endif
  107.  
  108. #ifdef FW_BUILD_WIN
  109.     return ::CreateEllipticRgnIndirect(&plfmRect);
  110. #endif
  111. }
  112.  
  113. //----------------------------------------------------------------------------------------
  114. //    FW_CreateRoundRectRegion
  115. //----------------------------------------------------------------------------------------
  116.  
  117. FW_FUNC_ATTR ODRgnHandle FW_CreateRoundRectRegion(const FW_CRect& rect, const FW_CPoint& ovalSize)
  118. {
  119.     FW_SPlatformRect plfmRect(rect);
  120.     FW_SPlatformPoint plfmPoint(ovalSize);
  121.  
  122. #ifdef FW_BUILD_MAC
  123.     GrafPtr svPort = FW_PrivMacOpenRegion();
  124.     ::FrameRoundRect(&plfmRect, plfmPoint.X(), plfmPoint.Y());
  125.     return ::FW_PrivMacCloseRegion(svPort);
  126. #endif
  127. #ifdef FW_BUILD_WIN
  128.     return ::CreateRoundRectRgn(plfmRect.left, plfmRect.top, 
  129.                                 plfmRect.right, plfmRect.bottom, 
  130.                                 plfmPoint.X(), plfmPoint.Y());
  131. #endif
  132. }
  133.  
  134. //----------------------------------------------------------------------------------------
  135. //    FW_CreateArcRegion
  136. //----------------------------------------------------------------------------------------
  137.  
  138. FW_FUNC_ATTR ODRgnHandle FW_CreateArcRegion(const FW_CRect& rect, short startAngle, short arcAngle)
  139. {
  140.     FW_SPlatformRect plfmRect = rect;
  141.  
  142.     // Create an elliptic region
  143. #ifdef FW_BUILD_MAC
  144.     GrafPtr savePort = ::FW_PrivMacOpenRegion();
  145.     ::FrameOval(&plfmRect);
  146.     ODRgnHandle hEllipticRgn = ::FW_PrivMacCloseRegion(savePort);
  147. #endif
  148. #ifdef FW_BUILD_WIN
  149.     // Create an elliptic region
  150.     HRGN hEllipticRgn = ::CreateEllipticRgnIndirect(&plfmRect);
  151. #endif
  152.  
  153.     short angle0 = startAngle,
  154.           angle1 = startAngle + arcAngle * 1 / 4,
  155.           angle2 = startAngle + arcAngle * 2 / 4,
  156.           angle3 = startAngle + arcAngle * 3 / 4,
  157.           angle4 = startAngle + arcAngle;
  158.           
  159.     short width = plfmRect.right - plfmRect.left;
  160.     short height = plfmRect.bottom - plfmRect.top;
  161.     FW_SPlatformRect polygonRect(plfmRect.left - width, plfmRect.top - height,
  162.                                  plfmRect.right + width, plfmRect.bottom + height);
  163.     
  164.     FW_SPlatformPoint pt[6];
  165.     
  166.     FW_PrivCalcArcPoints(polygonRect, angle0, pt[0]);
  167.     FW_PrivCalcArcPoints(polygonRect, angle1, pt[1]);
  168.     FW_PrivCalcArcPoints(polygonRect, angle2, pt[2]);
  169.     FW_PrivCalcArcPoints(polygonRect, angle3, pt[3]);
  170.     FW_PrivCalcArcPoints(polygonRect, angle4, pt[4]);
  171.     
  172.     pt[5].Set((plfmRect.left + plfmRect.right) / 2,
  173.               (plfmRect.top + plfmRect.bottom) / 2);
  174.  
  175.     // Create a polygon region
  176. #ifdef FW_BUILD_MAC
  177.      savePort = ::FW_PrivMacOpenRegion();
  178.     
  179.     ::MoveTo(pt[0].h, pt[0].v);
  180.     for(short i = 1; i < 6; i ++)
  181.         ::LineTo(pt[i].h, pt[i].v);
  182.  
  183.     ODRgnHandle hPolygonRgn = ::FW_PrivMacCloseRegion(savePort);
  184. #endif
  185. #ifdef FW_BUILD_WIN
  186.     ODRgnHandle hPolygonRgn = ::CreatePolygonRgn(pt, 6, WINDING);
  187. #endif
  188.  
  189.     // Intersect the regions
  190.     ODRgnHandle hArcRegion = ::FW_IntersectRegion(hEllipticRgn, hPolygonRgn);
  191.     
  192.     // Clean up
  193.     ::FW_DisposeRegion(hEllipticRgn);
  194.     ::FW_DisposeRegion(hPolygonRgn);
  195.     
  196.     // Return the result
  197.     return hArcRegion;
  198. }
  199.  
  200. //----------------------------------------------------------------------------------------
  201. //    FW_CreatePolygonRegion
  202. //----------------------------------------------------------------------------------------
  203.  
  204. FW_FUNC_ATTR ODRgnHandle FW_CreatePolygonRegion(unsigned long pointCount, const FW_CPoint* pointArray)
  205. {
  206. #ifdef FW_BUILD_MAC
  207.     GrafPtr savePort = ::FW_PrivMacOpenRegion();
  208.     
  209.     FW_SPlatformPoint pt = pointArray[0];
  210.     ::MoveTo(pt.h, pt.v);
  211.     
  212.     for(unsigned long i = 1; i < pointCount; i ++)
  213.     {
  214.         pt = pointArray[i];
  215.         ::LineTo(pt.h, pt.v);
  216.     }
  217.  
  218.     return ::FW_PrivMacCloseRegion(savePort);
  219. #endif
  220. #ifdef FW_BUILD_WIN
  221.     FW_SPlatformPoint* points = new FW_SPlatformPoint[pointCount];
  222.     
  223.     for(unsigned long i = 0; i < pointCount; i ++)
  224.         points[i] = pointArray[i];
  225.  
  226.     HRGN hRgn = ::CreatePolygonRgn(points, pointCount, ALTERNATE);
  227.     delete[] points;
  228.     
  229.     return hRgn;
  230. #endif
  231. }
  232.  
  233. //----------------------------------------------------------------------------------------
  234. //    FW_CreateLineRegion
  235. //----------------------------------------------------------------------------------------
  236.  
  237. FW_FUNC_ATTR ODRgnHandle FW_CreateLineRegion(const FW_CPoint& startPt,
  238.                                              const FW_CPoint& endPt,
  239.                                              const FW_CPoint& lineThickness)
  240. {
  241.     ODRgnHandle rgn;
  242.     
  243.     FW_SPlatformPoint firstPoint(startPt);
  244.     FW_SPlatformPoint lastPoint(endPt);
  245.     FW_SPlatformPoint penSize(lineThickness);
  246.     
  247.     FW_SPlatformRect halfPen(-penSize.X() / 2, -penSize.Y() / 2, (penSize.X() + 1) / 2, (penSize.Y() + 1) / 2);
  248.  
  249.     FW_SPlatformRect rect(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top, firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  250.  
  251.     short regionCode = 0;
  252.     if (lastPoint.X() < rect.left)
  253.         regionCode = 0x0008;
  254.     else if (lastPoint.X() > rect.right)
  255.         regionCode = 0x0004;
  256.     
  257.     if (lastPoint.Y() < rect.top)
  258.         regionCode |= 0x0001;
  259.     else if (lastPoint.Y() > rect.bottom)
  260.         regionCode |= 0x0002;
  261.  
  262.     short nbPoint;
  263.     FW_SPlatformPoint pt[6];
  264.     
  265.     switch (regionCode)
  266.     {
  267.         case 0x0000:
  268.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  269.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  270.             nbPoint = 2;
  271.             break;
  272.         case 0x0004:
  273.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  274.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  275.             nbPoint = 2;
  276.             break;
  277.         case 0x0008:
  278.             pt[0].Set(lastPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  279.             pt[1].Set(firstPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  280.             nbPoint = 2;
  281.             break;
  282.         case 0x0002:
  283.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  284.             pt[1].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  285.             nbPoint = 2;
  286.             break;
  287.         case 0x0001:
  288.             pt[0].Set(firstPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  289.             pt[1].Set(lastPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  290.             nbPoint = 2;
  291.             break;
  292.         case 0x0005:
  293.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  294.             pt[1].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  295.             pt[2].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  296.             pt[3].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  297.             pt[4].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  298.             pt[5].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  299.             nbPoint = 6;
  300.             break;
  301.         case 0x0006:
  302.             pt[0].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  303.             pt[1].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  304.             pt[2].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  305.             pt[3].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  306.             pt[4].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  307.             pt[5].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  308.             nbPoint = 6;
  309.             break;
  310.         case 0x000A:
  311.             pt[0].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.top);
  312.             pt[1].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  313.             pt[2].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  314.             pt[3].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.bottom);
  315.             pt[4].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  316.             pt[5].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  317.             nbPoint = 6;
  318.             break;
  319.         case 0x0009:
  320.             pt[0].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.top);
  321.             pt[1].Set(firstPoint.X() + halfPen.right, firstPoint.Y() + halfPen.bottom);
  322.             pt[2].Set(firstPoint.X() + halfPen.left, firstPoint.Y() + halfPen.bottom);
  323.             pt[3].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.bottom);
  324.             pt[4].Set(lastPoint.X() + halfPen.left, lastPoint.Y() + halfPen.top);
  325.             pt[5].Set(lastPoint.X() + halfPen.right, lastPoint.Y() + halfPen.top);
  326.             nbPoint = 6;
  327.             break;
  328.     }
  329.     
  330. #ifdef FW_BUILD_WIN
  331.     if (nbPoint == 2)
  332.         rgn = ::CreateRectRgn(pt[0].x, pt[0].y, pt[1].x, pt[1].y);
  333.     else
  334.         rgn = ::CreatePolygonRgn(pt, nbPoint, WINDING);
  335. #endif        
  336.     
  337. #ifdef FW_BUILD_MAC
  338.     if (nbPoint == 2)
  339.     {
  340.         rgn = ::NewRgn();
  341.         FW_SPlatformRect rect(pt[0], pt[1]);
  342.         ::RectRgn(rgn, &rect);
  343.     }
  344.     else
  345.     {
  346.         GrafPtr svPort = ::FW_PrivMacOpenRegion();
  347.         ::MoveTo(pt[0].h, pt[0].v);
  348.         ::LineTo(pt[1].h, pt[1].v);
  349.         ::LineTo(pt[2].h, pt[2].v);            
  350.         ::LineTo(pt[3].h, pt[3].v);
  351.         ::LineTo(pt[4].h, pt[4].v);            
  352.         ::LineTo(pt[5].h, pt[5].v);
  353.         ::LineTo(pt[0].h, pt[0].v);
  354.         rgn = ::FW_PrivMacCloseRegion(svPort);
  355.     }
  356. #endif
  357.  
  358.     return rgn;
  359. }
  360.  
  361. //----------------------------------------------------------------------------------------
  362. //    FW_CopyRegion
  363. //----------------------------------------------------------------------------------------
  364.  
  365. FW_FUNC_ATTR ODRgnHandle FW_CopyRegion(ODRgnHandle scrRgn)
  366. {
  367.     FW_ASSERT(scrRgn != NULL);
  368.     
  369. #ifdef FW_BUILD_MAC
  370.     ODRgnHandle newRgn = ::NewRgn();
  371.     ::CopyRgn(scrRgn, newRgn);
  372.     return newRgn;
  373. #endif
  374. #ifdef FW_BUILD_WIN
  375.     ODRgnHandle newRgn = ::CreateRectRgn(0,0,0,0);
  376.     ::CombineRgn(newRgn, scrRgn, NULL, RGN_COPY);
  377.     return newRgn;
  378. #endif
  379. }
  380.  
  381. //----------------------------------------------------------------------------------------
  382. //    FW_CopyRegion
  383. //----------------------------------------------------------------------------------------
  384.  
  385. FW_FUNC_ATTR void FW_CopyRegion(ODRgnHandle scrRgn, ODRgnHandle dstRgn)
  386. {
  387.     FW_ASSERT(scrRgn != NULL);
  388.     FW_ASSERT(dstRgn != NULL);
  389.     
  390. #ifdef FW_BUILD_MAC
  391.     ::CopyRgn(scrRgn, dstRgn);
  392. #endif
  393. #ifdef FW_BUILD_WIN
  394.     ::CombineRgn(dstRgn, scrRgn, NULL, RGN_COPY);
  395. #endif
  396. }
  397.  
  398. //----------------------------------------------------------------------------------------
  399. //    FW_DisposeRegion
  400. //----------------------------------------------------------------------------------------
  401.  
  402. FW_FUNC_ATTR void FW_DisposeRegion(ODRgnHandle rgn)
  403. {
  404.     FW_ASSERT(rgn);
  405.     
  406. #ifdef FW_BUILD_MAC
  407.     ::DisposeRgn(rgn);
  408. #endif
  409. #ifdef FW_BUILD_WIN
  410.     ::DeleteObject(rgn);
  411. #endif
  412. }
  413.  
  414. //----------------------------------------------------------------------------------------
  415. //    FW_WriteRegion
  416. //----------------------------------------------------------------------------------------
  417.  
  418. FW_FUNC_ATTR void FW_WriteRegion(ODRgnHandle rgnHandle, FW_CWritableStream& stream)
  419. {
  420. #ifdef FW_BUILD_WIN
  421.     long size = ::GetRegionData(rgnHandle, 0, NULL);
  422.     
  423.     FW_CAcquireTemporarySystemHandle memHandle(size);
  424.     LPRGNDATA rgnData = (LPRGNDATA) memHandle.GetPointer();
  425.     ::GetRegionData(rgnHandle, size, rgnData);
  426.     
  427.     stream << size;
  428.     stream.Write(rgnData, size);
  429. #endif
  430. #ifdef FW_BUILD_MAC
  431.     short size = (*rgnHandle)->rgnSize;
  432.     
  433.     FW_CAcquireLockedSystemHandle memHandle((FW_PlatformHandle)rgnHandle);
  434.     void* rgnData = memHandle.GetPointer();
  435.     
  436.     stream << size;
  437.     stream.Write(rgnData, size);
  438. #endif
  439. }
  440.  
  441. //----------------------------------------------------------------------------------------
  442. //    FW_ReadRegion
  443. //----------------------------------------------------------------------------------------
  444.  
  445. FW_FUNC_ATTR ODRgnHandle FW_ReadRegion(FW_CReadableStream& stream)
  446. {
  447. #ifdef FW_BUILD_WIN
  448.     long size;
  449.     stream >> size;
  450.     
  451.     FW_CAcquireTemporarySystemHandle memHandle(size);
  452.     LPRGNDATA rgnData = (LPRGNDATA) memHandle.GetPointer();
  453.     stream.Read(rgnData, size);
  454.  
  455.     return ::ExtCreateRegion(NULL, size, rgnData);
  456. #endif
  457. #ifdef FW_BUILD_MAC
  458.     short size;
  459.     stream >> size;
  460.     
  461.     FW_CAcquireTemporarySystemHandle memHandle(size);
  462.     void* rgnData = memHandle.GetPointer();
  463.     
  464.     stream.Read(rgnData, size);
  465.  
  466.     memHandle.Orphan();
  467.     return (ODRgnHandle) memHandle.GetPlatformHandle();
  468. #endif
  469. }
  470.  
  471. //----------------------------------------------------------------------------------------
  472. //    FW_GetRegionBoundingBox
  473. //----------------------------------------------------------------------------------------
  474.  
  475. FW_FUNC_ATTR void FW_GetRegionBoundingBox(ODRgnHandle rgn, FW_CRect& rect)
  476. {
  477. #ifdef FW_BUILD_MAC
  478.     rect = (*rgn)->rgnBBox;
  479. #endif
  480. #ifdef FW_BUILD_WIN
  481.     FW_SPlatformRect plfmRect;
  482.     ::GetRgnBox(rgn, &plfmRect);
  483.     rect = plfmRect;
  484. #endif
  485. }
  486.  
  487. //----------------------------------------------------------------------------------------
  488. //    FW_PointInRegion
  489. //----------------------------------------------------------------------------------------
  490.  
  491. FW_FUNC_ATTR FW_Boolean FW_PointInRegion(ODRgnHandle rgn, const FW_CPoint& point)
  492. {
  493.     FW_SPlatformPoint plfmPt = point;
  494. #ifdef FW_BUILD_MAC
  495.     return ::PtInRgn(plfmPt, rgn);
  496. #endif
  497. #ifdef FW_BUILD_WIN
  498.     return ::PtInRegion(rgn, plfmPt.X(), plfmPt.Y());
  499. #endif
  500. }
  501.  
  502. //----------------------------------------------------------------------------------------
  503. //    FW_RectInRegion
  504. //----------------------------------------------------------------------------------------
  505.  
  506. FW_FUNC_ATTR FW_Boolean FW_RectInRegion(ODRgnHandle rgn, const FW_CRect& rect)
  507. {
  508.     FW_SPlatformRect plfmRect = rect;
  509. #ifdef FW_BUILD_MAC
  510.     return ::RectInRgn(&plfmRect, rgn);
  511. #endif
  512. #ifdef FW_BUILD_WIN
  513.     return ::RectInRegion(rgn, &plfmRect);
  514. #endif
  515. }
  516.  
  517. //----------------------------------------------------------------------------------------
  518. //    FW_UnionRegion
  519. //----------------------------------------------------------------------------------------
  520.  
  521. FW_FUNC_ATTR ODRgnHandle FW_UnionRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  522. {
  523.     ODRgnHandle dstRgn = ::FW_NewRegion();
  524.     
  525. #ifdef FW_BUILD_MAC
  526.     ::UnionRgn(rgn1, rgn2, dstRgn);
  527. #endif
  528. #ifdef FW_BUILD_WIN
  529.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_OR);
  530. #endif
  531.     
  532.     return dstRgn;
  533. }
  534.  
  535. //----------------------------------------------------------------------------------------
  536. //    FW_XorRegion
  537. //----------------------------------------------------------------------------------------
  538.  
  539. FW_FUNC_ATTR ODRgnHandle FW_XorRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  540. {
  541.     ODRgnHandle dstRgn = ::FW_NewRegion();
  542.     
  543. #ifdef FW_BUILD_MAC
  544.     ::XorRgn(rgn1, rgn2, dstRgn);
  545. #endif
  546. #ifdef FW_BUILD_WIN
  547.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_XOR);
  548. #endif
  549.  
  550.     return dstRgn;
  551. }
  552.  
  553. //----------------------------------------------------------------------------------------
  554. //    FW_SubtractRegion
  555. //----------------------------------------------------------------------------------------
  556.  
  557. FW_FUNC_ATTR ODRgnHandle FW_SubtractRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  558. {
  559.     ODRgnHandle dstRgn = ::FW_NewRegion();
  560.     
  561. #ifdef FW_BUILD_MAC
  562.     ::DiffRgn(rgn1, rgn2, dstRgn);
  563. #endif
  564. #ifdef FW_BUILD_WIN
  565.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_DIFF);
  566. #endif
  567.  
  568.     return dstRgn;
  569. }
  570.  
  571. //----------------------------------------------------------------------------------------
  572. //    FW_IntersectRegion
  573. //----------------------------------------------------------------------------------------
  574.  
  575. FW_FUNC_ATTR ODRgnHandle FW_IntersectRegion(ODRgnHandle rgn1, ODRgnHandle rgn2)
  576. {
  577.     ODRgnHandle dstRgn = ::FW_NewRegion();
  578.     
  579. #ifdef FW_BUILD_MAC
  580.     ::SectRgn(rgn1, rgn2, dstRgn);
  581. #endif
  582. #ifdef FW_BUILD_WIN
  583.     ::CombineRgn(dstRgn, rgn1, rgn2, RGN_AND);
  584. #endif
  585.  
  586.     return dstRgn;
  587. }
  588.  
  589. //----------------------------------------------------------------------------------------
  590. //    FW_OutlineRegion
  591. //----------------------------------------------------------------------------------------
  592.  
  593. FW_FUNC_ATTR void FW_OutlineRegion(ODRgnHandle rgn, FW_CFixed outlineSize)
  594. {
  595.     ODRgnHandle tempRgn = ::FW_CopyRegion(rgn);
  596.     
  597.     if (outlineSize <= FW_kFixed0)
  598.         outlineSize = FW_kFixedPos1;
  599.     
  600.     ::FW_InsetRegion(tempRgn, outlineSize, outlineSize);
  601.     
  602.     ::FW_SubtractRegion(rgn, tempRgn, rgn);
  603.  
  604.     ::FW_DisposeRegion(tempRgn);
  605. }
  606.  
  607. #ifdef FW_BUILD_WIN
  608.  
  609. //----------------------------------------------------------------------------------------
  610. //    FW_PrivWinInsetRegionPoint
  611. //----------------------------------------------------------------------------------------
  612.  
  613. static void FW_PrivWinInsetRegionRectangle(LPPOINT lppt, int dx, int dy, const POINT& ptCenter)
  614. {
  615.     if(lppt->x < ptCenter.x)
  616.     {
  617.         lppt->x += dx;
  618.         if(lppt->x > ptCenter.x)
  619.             lppt->x = ptCenter.x;
  620.     }
  621.     else
  622.     {
  623.         lppt->x -= dx;
  624.         if(lppt->x < ptCenter.x)
  625.             lppt->x = ptCenter.x;
  626.     }
  627.  
  628.     if(lppt->y < ptCenter.y)
  629.     {
  630.         lppt->y += dy;
  631.         if(lppt->y > ptCenter.y)
  632.             lppt->y = ptCenter.y;
  633.     }
  634.     else
  635.     {
  636.         lppt->y -= dy;
  637.         if(lppt->y < ptCenter.y)
  638.             lppt->y = ptCenter.y;
  639.     }
  640. }
  641.  
  642. //----------------------------------------------------------------------------------------
  643. //    FW_PrivWinInsetRegionRectangle
  644. //----------------------------------------------------------------------------------------
  645.  
  646. static void FW_PrivWinInsetRegionRectangle(LPRECT lpRect, int dx, int dy, const POINT& ptCenter)
  647. {
  648.     FW_PrivWinInsetRegionRectangle(((LPPOINT) lpRect) + 0, dx, dy, ptCenter);
  649.     FW_PrivWinInsetRegionRectangle(((LPPOINT) lpRect) + 1, dx, dy, ptCenter);
  650. }
  651.  
  652. #endif
  653.  
  654. //----------------------------------------------------------------------------------------
  655. //    FW_InsetRegion
  656. //----------------------------------------------------------------------------------------
  657.  
  658. FW_FUNC_ATTR void FW_InsetRegion(ODRgnHandle rgn, FW_CFixed x, FW_CFixed y)
  659. {
  660. #ifdef FW_BUILD_MAC
  661.     ::InsetRgn(rgn, x.AsInt(), y.AsInt());
  662. #endif
  663. #ifdef FW_BUILD_WIN
  664.     // Note: This code relies on partially documented Windows GDI data structures!
  665.  
  666.     // Get the current region data
  667.     long size = ::GetRegionData(rgn, 0, NULL);
  668.     
  669.     FW_CAcquireTemporarySystemHandle memHandle(size);
  670.     LPRGNDATA rgnData = (LPRGNDATA) memHandle.GetPointer();
  671.     ::GetRegionData(rgn, size, rgnData);
  672.     
  673.     // Mess with region data
  674.     int dx = x.AsInt();
  675.     int dy = y.AsInt();
  676.     
  677.     if(rgnData->rdh.iType == RDH_RECTANGLES)
  678.     {
  679.         POINT ptCenter;
  680.         ptCenter.x = (rgnData->rdh.rcBound.left + rgnData->rdh.rcBound.right) / 2;
  681.         ptCenter.y = (rgnData->rdh.rcBound.top  + rgnData->rdh.rcBound.bottom) / 2;
  682.         
  683.         LPRECT lpRect = (LPRECT) rgnData->Buffer;
  684.  
  685.         for(unsigned long i = 0; i < rgnData->rdh.nCount; ++ i, ++ lpRect)
  686.             ::FW_PrivWinInsetRegionRectangle(lpRect, dx, dy, ptCenter);
  687.     }
  688.  
  689.     // Create a new region and replace the one passed in    
  690.     HRGN hNewRgn = ::ExtCreateRegion(NULL, size, rgnData);
  691.     if(hNewRgn == NULL)
  692.         FW_Failure(FW_xMemoryExhausted);
  693.  
  694.     ::FW_CopyRegion(hNewRgn, rgn);
  695.     ::FW_DisposeRegion(hNewRgn);
  696. #endif
  697. }
  698.  
  699. //----------------------------------------------------------------------------------------
  700. //    FW_MapRegion
  701. //----------------------------------------------------------------------------------------
  702.  
  703. FW_FUNC_ATTR void FW_MapRegion(ODRgnHandle rgn, const FW_CRect& srcRect, const FW_CRect& dstRect)
  704. {
  705.     FW_SPlatformRect plfmSrc(srcRect);
  706.     FW_SPlatformRect plfmDst(dstRect);
  707.     
  708. #ifdef FW_BUILD_MAC
  709.     ::MapRgn(rgn, &plfmSrc, &plfmDst);
  710. #endif
  711. #ifdef FW_BUILD_WIN
  712.     // Get the current region data
  713.     long size = ::GetRegionData(rgn, 0, NULL);
  714.     
  715.     FW_CAcquireTemporarySystemHandle memHandle(size);
  716.     LPRGNDATA rgnData = (LPRGNDATA) memHandle.GetPointer();
  717.     ::GetRegionData(rgn, size, rgnData);
  718.  
  719.     // Figure out the desired transform
  720.     XFORM xform;
  721.     xform.eM11 = (dstRect.Width() / srcRect.Width()).AsDouble();
  722.     xform.eM12 = 0;
  723.     xform.eM21 = 0;
  724.     xform.eM22 = (dstRect.Height() / srcRect.Height()).AsDouble();
  725.     xform.eDx  = (dstRect.left - srcRect.left).AsDouble();
  726.     xform.eDy  = (dstRect.top  - srcRect.top).AsDouble();
  727.  
  728.     // Create a new region and replace the one passed in    
  729.     HRGN hNewRgn = ::ExtCreateRegion(&xform, size, rgnData);
  730.     if(hNewRgn == NULL)
  731.         FW_Failure(FW_xMemoryExhausted);
  732.  
  733.     ::FW_CopyRegion(hNewRgn, rgn);
  734.     ::FW_DisposeRegion(hNewRgn);
  735. #endif
  736. }
  737.  
  738. #ifdef FW_BUILD_MAC
  739. //----------------------------------------------------------------------------------------
  740. //    FW_PrivMacOpenRegion
  741. //----------------------------------------------------------------------------------------
  742.  
  743. GrafPtr FW_PrivMacOpenRegion()
  744. {
  745.     GrafPtr svPort;
  746.     ::GetPort(&svPort);
  747.     ::SetPort(FW_gScratchWindow);
  748.     ::OpenRgn();
  749.     return svPort;
  750. }
  751. #endif
  752.  
  753. #ifdef FW_BUILD_MAC
  754. //----------------------------------------------------------------------------------------
  755. //    FW_PrivMacCloseRegion
  756. //----------------------------------------------------------------------------------------
  757.  
  758. ODRgnHandle FW_PrivMacCloseRegion(GrafPtr svPort)
  759. {
  760.     ODRgnHandle hRgn = ::NewRgn();
  761.     ::CloseRgn(hRgn);
  762.     ::SetPort(svPort);
  763.     return hRgn;
  764. }
  765. #endif
  766.